package com.hd.service.activiti.impl;

import com.hd.commons.exception.MyException;
import com.hd.controller.activiti.util.cmd.*;
import com.hd.dao.BaseDao;
import com.hd.dao.JdbcDao;
import com.hd.entity.activiti.*;
import com.hd.entity.sys.User;
import com.hd.service.activiti.ActivitiService;
import com.hd.service.activiti.CommentEntityService;
import com.hd.service.activiti.ElementDefService;
import com.hd.service.activiti.WorkflowService;
import com.hd.service.sys.UserService;
import com.hd.util.StringUtils;
import com.hd.util.result.Page;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.*;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;

@Service("activitiService")
public class ActivitiServiceImpl implements ActivitiService {
	private static final Logger log = LoggerFactory.getLogger(ActivitiServiceImpl.class);
	@Autowired
	private TaskService taskService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private IdentityService identityService;
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private UserService userService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private ProcessEngineFactoryBean processEngineFactory;
	@Autowired
	private ProcessEngineConfiguration processEngineConfiguration;
	@Autowired
	private ElementDefService elementDefService;
	@Autowired
	private WorkflowService workflowService;
	@Autowired
	private CommentEntityService commentEntityService;
	@Autowired
	private ProcessEngine processEngine;
	@Autowired
	private BaseDao<ProcessInstanceEntity,String>processInstanceEntityDao;
	@Autowired
	protected JdbcDao jdbcDao;

	/**
	 * 通过流程实例ID查询流程实例运行过的流程节点
	 * 
	 * @param processInstanceId
	 *            流程实例ID
	 * @return
	 */
	@Override
	public List<HistoricActivityInstance> getHistoricActivityInstanceByProcessInstanceId(String processInstanceId) {
		List<HistoricActivityInstance> hactivityInstances = historyService.createHistoricActivityInstanceQuery()
				.processInstanceId(processInstanceId).list();
		return hactivityInstances;
	}

	/**
	 * 完成任务
	 * 
	 * @param taskId
	 *            任务id
	 * @param content
	 *            评论内容
	 * @param userid
	 *            评论用户
	 * @param variables
	 *            设置变量
	 */
	@Override
	public void completeTask(String taskId, String content, String userid, Map<String, Object> variables) {
		// 根据任务id查询任务
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		// 查询流程实例ID
		String processInstanceId = task.getProcessInstanceId();
		// 设置评论人
		identityService.setAuthenticatedUserId(userid);
		// 添加评论
		taskService.addComment(taskId, processInstanceId, content);
		// 完成委派任务
		if (DelegationState.PENDING == task.getDelegationState()) {
			taskService.resolveTask(taskId, variables);
			return;
		}
		// 正常完成任务
		taskService.complete(taskId, variables);
		saveCommentEntity(taskId);
	}

	protected void saveCommentEntity(String taskId) {
		List<Comment> comments = taskService.getTaskComments(taskId);
		for (Comment comment : comments) {
			CommentEntity commentEntity = new CommentEntity();
			commentEntity.setComment(comment.getFullMessage());
			commentEntity.setTaskId(taskId);
			commentEntity.setTime(comment.getTime());
			commentEntity.setType(CommentEntity.COMMENT_TYPE);
			User user = userService.get(comment.getUserId());
			if (user != null) {
				commentEntity.setUserName(user.getName());
			}
			commentEntity.setUserid(comment.getUserId());
			// 查询历史任务
			HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(comment.getTaskId())
					.singleResult();
			commentEntity.setTaskKey(task.getTaskDefinitionKey());
			commentEntity.setPrint(1);
			commentEntity.setTaskName(task.getName());
			commentEntity.setProcessInstanceId(task.getProcessInstanceId());
			commentEntityService.save(commentEntity);
		}

	}

	/**
	 * 通过流程实例ID查询所有的评论
	 * 
	 * @param processInstanceId
	 *            流程实例ID
	 * @return
	 */
	@Override
	public List<CommentVO> getCommentsByProcessInstanceId(String processInstanceId) {
		List<Comment> comments = taskService.getProcessInstanceComments(processInstanceId);
		List<CommentVO> commentVOs = new ArrayList<CommentVO>();
		for (int i = 0; i < comments.size(); i++) {
			CommentVO vo = new CommentVO();
			vo.setProcessInstanceId(processInstanceId);
			vo.setUserid(comments.get(i).getUserId());
			vo.setTaskId(comments.get(i).getTaskId());
			vo.setTime(comments.get(i).getTime());
			vo.setComment(comments.get(i).getFullMessage());
			User user = userService.get(comments.get(i).getUserId());
			if (user != null) {
				vo.setUserName(user.getName());
			}
			// 查询历史任务
			HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery()
					.taskId(comments.get(i).getTaskId()).singleResult();
			vo.setTaskName(task.getName());
			commentVOs.add(vo);
		}
		return commentVOs;
	}

	/**
	 * 通过任务ID查询评论
	 * 
	 * @param taskId
	 *            任务ID
	 * @return
	 */
	@Override
	public List<Comment> getCommentsByTaskId(String taskId) {
		List<Comment> comments = taskService.getTaskComments(taskId);
		return comments;
	}

	/**
	 * 启动流程
	 * 
	 * @param processDefKey
	 *            流程定义key
	 * @return
	 */
	@Override
	public ProcessInstance startProcessInstance(String processDefKey) {
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefKey);
		return processInstance;
	}

	@Override
	public List<BaseVO> findTodoTask(User user, Page<BaseVO> page) throws Exception {
		// taskCandidateOrAssigned查询某个人的待办任务，包含已签收、候选任务<候选人范围和候选组范围>
		Map<String,Object>condition=page.getCondition();
		TaskQuery taskQuery=null;
		if(StringUtils.isNotNull(condition.get("param"))) {
			log.info("param={}",condition.get("param").toString());
			log.info("是否是数字："+StringUtils.isNumeric(condition.get("param").toString()));
			if(StringUtils.isNumeric(condition.get("param").toString())) {
				taskQuery = this.taskService.createTaskQuery().taskCandidateOrAssigned(user.getId()
						.toString()).processInstanceId(condition.get("param").toString());
			}else {
				List<String>processInstanceIds=getProcessInstanceEntityLikeTitle(condition.get("param").toString());
				taskQuery=this.taskService.createTaskQuery().taskCandidateOrAssigned(user.getId()
						.toString()).processInstanceIdIn(processInstanceIds);
			}
		}else {
			taskQuery = this.taskService.createTaskQuery().taskCandidateOrAssigned(user.getId().toString());
		}
		Integer totalSum = Integer.parseInt(""+taskQuery.count());;
		int[] pageParams = page.getPageParams(totalSum);
		List<Task> tasks = taskQuery.orderByTaskCreateTime().desc().listPage(pageParams[0],
				pageParams[1]);
		List<BaseVO> taskList = getBaseVOList(tasks);
		return taskList;
	}

	/**
	 * 将Task集合转为BaseVO集合
	 * 
	 * @param tasks
	 * @return
	 */
	protected List<BaseVO> getBaseVOList(List<Task> tasks) {
		List<BaseVO> taskList = new ArrayList<BaseVO>();
		for (Task task : tasks) {
			String processInstanceId = task.getProcessInstanceId();
			ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
					.processInstanceId(processInstanceId).active().singleResult();
			if (processInstance == null) {
				// 如果有挂起的流程则continue
				continue;
			}
			// 获取当前流程下的key为entity的variable
			BaseVO base = (BaseVO) this.runtimeService.getVariable(processInstance.getId(), "entity");
			base.setTask(task);
			base.setProcessInstance(processInstance);
			base.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
			taskList.add(base);
		}
		return taskList;
	}

	/**
	 * 查询流程定义对象
	 *
	 * @param processDefinitionId
	 *            流程定义ID
	 * @return
	 */
	protected ProcessDefinition getProcessDefinition(String processDefinitionId) {
		ProcessDefinition processDefinition = this.repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		return processDefinition;
	}

	/**
	 * 高亮显示追踪流程 不含中文乱码
	 * @param processInstanceId
	 * @return
	 * @throws Exception
	 */
	@Override
	public InputStream getDiagram(String processInstanceId) throws Exception {
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
		List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
		// 不使用spring请使用下面的两行代码
		// ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl)
		// ProcessEngines.getDefaultProcessEngine();
		// Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());
		// 使用spring注入引擎请使用下面的这行代码
		processEngineConfiguration = processEngineFactory.getProcessEngineConfiguration();
		Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
		// 通过引擎生成png图片，并标记当前节点,并把当前节点用红色边框标记出来，弊端和直接部署流程文件生成的图片问题一样-乱码！。
		ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
		InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds,
				Collections.<String> emptyList(), this.processEngineConfiguration.getActivityFontName(),
				this.processEngineConfiguration.getLabelFontName(),
				this.processEngineConfiguration.getAnnotationFontName(),
				null, 1.0);
		return imageStream;
	}



	/**
	 * 显示图片-通过流程ID，，不带流程跟踪(没有乱码问题)
	 * 
	 * @param resourceType
	 * @param processInstanceId
	 * @return
	 */
	@Override
	public InputStream getDiagramByProInstanceId_noTrace(String resourceType, String processInstanceId)
			throws Exception {
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();

		String resourceName = "";
		if (resourceType.equals("png") || resourceType.equals("image")) {
			resourceName = processDefinition.getDiagramResourceName();
		} else if (resourceType.equals("xml")) {
			resourceName = processDefinition.getResourceName();
		}
		InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
				resourceName);
		return resourceAsStream;
	}

	/**
	 * 显示图片-通过流程ID，，不带流程跟踪(没有乱码问题)
	 * 
	 * @param resourceType
	 * @param processInstanceId
	 * @return
	 */
	@Override
	public InputStream getDiagramByProInstanceId_noTrace2(String resourceType, String processInstanceId)
			throws Exception {
		HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();

		String resourceName = "";
		if (resourceType.equals("png") || resourceType.equals("image")) {
			resourceName = processDefinition.getDiagramResourceName();
		} else if (resourceType.equals("xml")) {
			resourceName = processDefinition.getResourceName();
		}
		InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
				resourceName);
		return resourceAsStream;
	}

	/**
	 * 显示图片-通过部署ID，不带流程跟踪(没有乱码啊问题)
	 * 
	 * @param resourceType
	 * @param processDefinitionId
	 * @return
	 * @throws Exception
	 */
	@Override
	public InputStream getDiagramByProDefinitionId_noTrace(String resourceType, String processDefinitionId)
			throws Exception {
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		String resourceName = "";
		if (resourceType.equals("png") || resourceType.equals("image")) {
			resourceName = processDefinition.getDiagramResourceName();
		} else if (resourceType.equals("xml")) {
			resourceName = processDefinition.getResourceName();
		}
		InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
				resourceName);
		return resourceAsStream;
	}

	/**
	 * 创建开始节点
	 * 
	 * @return
	 */
	protected static StartEvent createStartEvent() {
		StartEvent startEvent = new StartEvent();
		startEvent.setId("startEvent");
		startEvent.setName("start");
		startEvent.setInitiator("startUserId");
		return startEvent;
	}

	/**
	 * 创建结束节点
	 * 
	 * @return
	 */
	protected static EndEvent createEndEvent() {
		EndEvent endEvent = new EndEvent();
		endEvent.setId("endEvent");
		endEvent.setName("end");
		return endEvent;
	}

	/**
	 * 创建用户任务节点
	 * 
	 * @param id
	 * @param name
	 * @return
	 */
	protected static UserTask createUserTask(String id, String name) {
		List<ActivitiListener> taskListeners = new ArrayList<ActivitiListener>();
		ActivitiListener listener = new ActivitiListener();
		listener.setId("");
		listener.setEvent("create");
		listener.setImplementationType("delegateExpression");
		listener.setImplementation("${userTaskListener}");
		taskListeners.add(listener);

		UserTask userTask = new UserTask();
		userTask.setId(id);
		userTask.setName(name);
		userTask.setTaskListeners(taskListeners);
		userTask.setDocumentation(""); // 说明
		return userTask;
	}

	/**
	 * 创建节点间的连线
	 * 
	 * @param from
	 * @param to
	 * @param id
	 * @param name
	 * @param conditionExpression
	 * @return
	 */
	protected static SequenceFlow createSequenceFlow(String from, String to, String id, String name,
			String conditionExpression) {
		SequenceFlow flow = new SequenceFlow();
		flow.setId(id);
		flow.setName(name);
		flow.setSourceRef(from);
		flow.setTargetRef(to);
		if (StringUtils.isNotBlank(conditionExpression)) {
			flow.setConditionExpression(conditionExpression);
		}
		return flow;
	}

	/**
	 * 创建排他网关
	 * 
	 * @param id
	 * @return
	 */
	protected static ExclusiveGateway createExclusiveGateway(String id) {
		ExclusiveGateway gateway = new ExclusiveGateway();
		gateway.setId(id);
		return gateway;
	}

	/**
	 * 查询下一个节点
	 * 
	 * @throws Exception
	 */
	@Override
	public List<ElementDef> getNextElementDefs(String procdefKey, String key) throws Exception {
		// 查询最新版的流程定义
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionKey(procdefKey).latestVersion().singleResult();
		// 流程起始节点的下一步节点
		if (key == null) {
			try {
				ElementDef startElement = elementDefService.getStartElement(processDefinition.getId());
				key = startElement.getKey();
			} catch (Exception e) {
				throw new MyException("流程设置错误！没有在表【act_element_ins、act_element_def】中设置起始节点的下一个节点配置！");
			}
		}
		return elementDefService.getNextElementDefs(processDefinition.getId(), key);
	}

	/**
	 * 签收任务
	 */
	@Override
	public void doClaim(User user, String taskId) {
		this.identityService.setAuthenticatedUserId(user.getId().toString());
		this.taskService.claim(taskId, user.getId().toString());
		doClaimComment(taskId, user.getId().toLowerCase());
	}

	protected void doClaimComment(String taskId, String userId) {
		CommentEntity commentEntity = new CommentEntity();
		commentEntity.setTaskId(taskId);
		commentEntity.setTime(new Date());
		commentEntity.setType(CommentEntity.COMMENT_CLAIM);
		User user = null;
		if (StringUtils.isNotNull(userId)) {
			user = userService.get(userId);
			if (user != null) {
				commentEntity.setUserName(user.getName());
			}
			commentEntity.setUserid(userId);
		}
		// 查询历史任务
		HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
		commentEntity.setTaskName(task.getName());
		commentEntity.setProcessInstanceId(task.getProcessInstanceId());
		String comment = "";
		if (user != null) {
			comment = user.getName() + "签收任务【" + task.getName() + "】";
		}
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}

	/**
	 * 反签收
	 * 
	 * @param taskId
	 */
	@Override
	public void doUnClaim(String taskId) {
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		// 受理人
		String assignee = task.getAssignee();
		// 反签收条件过滤:有一个任务的相关的候选人、候选组就可以反签收
		List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskId);
		boolean flag = false;
		if (identityLinks.size() > 0) {
			for (IdentityLink identityLink : identityLinks) {
				if (identityLink.getType().equals(IdentityLinkType.CANDIDATE)) {
					flag = true;
					break;
				}
			}
		}
		if (flag) {
			taskService.claim(taskId, null);
			doUnClaimComment(taskId, assignee);
		} else {
			throw new MyException("任务ID为【" + taskId + "】的任务不能进行反签收！");
		}
	}

	/**
	 * 保存反签收操作
	 * 
	 * @param taskId
	 * @param assignee
	 */
	protected void doUnClaimComment(String taskId, String assignee) {
		CommentEntity commentEntity = new CommentEntity();
		commentEntity.setTaskId(taskId);
		commentEntity.setTime(new Date());
		commentEntity.setType(CommentEntity.COMMENT_UNCLAIM);
		User user = null;
		if (StringUtils.isNotNull(assignee)) {
			user = userService.get(assignee);
			if (user != null) {
				commentEntity.setUserName(user.getName());
			}
			commentEntity.setUserid(assignee);
		}
		// 查询历史任务
		HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
		commentEntity.setTaskName(task.getName());
		commentEntity.setProcessInstanceId(task.getProcessInstanceId());
		String comment = "";
		if (user != null) {
			comment = user.getName() + "反签收任务【" + task.getName() + "】";
		}
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}

	/**
	 * 委派任务
	 */
	@Override
	public void doDelegateTask(String userId, String taskId) throws Exception {
		// API: If no owner is set on the task, the owner is set to the current assignee
		// of the task.
		// OWNER_（委托人）：受理人委托其他人操作该TASK的时候，受理人就成了委托人OWNER_，其他人就成了受理人ASSIGNEE_
		// assignee容易理解，主要是owner字段容易误解，owner字段就是用于受理人委托别人操作的时候运用的字段
		Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
		this.taskService.delegateTask(taskId, userId);
		doDelegateTaskComment(taskId, task.getAssignee(), userId);
	}

	// 委派信息
	protected void doDelegateTaskComment(String taskId, String assign, String userId) {
		CommentEntity commentEntity = new CommentEntity();
		commentEntity.setTaskId(taskId);
		commentEntity.setTime(new Date());
		commentEntity.setType(CommentEntity.COMMENT_DELEGATETASK);
		User user = null;
		if (StringUtils.isNotNull(assign)) {
			user = userService.get(assign);
			if (user != null) {
				commentEntity.setUserName(user.getName());
			}
			commentEntity.setUserid(assign);
		}

		// 查询历史任务
		HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
		commentEntity.setTaskName(task.getName());
		commentEntity.setProcessInstanceId(task.getProcessInstanceId());
		User user1 = userService.get(userId);
		String comment = "";
		if (user1 != null) {
			if (user != null) {
				comment = user.getName() + "委派任务【" + task.getName() + "】给" + user1.getName();
			} else {
				comment = "委派任务【" + task.getName() + "】给" + user1.getName();
			}
		}
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}

	/**
	 * 转办任务
	 */
	@Override
	public void doTransferTask(String userId, String taskId) throws Exception {
		Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
		if (task != null) {
			String assign = task.getAssignee();
			this.taskService.setAssignee(taskId, userId);
			this.taskService.setOwner(taskId, assign);
			doTransferTaskComment(taskId, assign, userId);
		} else {
			throw new ActivitiObjectNotFoundException("任务不存在！", this.getClass());
		}
	}

	// 转办信息
	protected void doTransferTaskComment(String taskId, String assign, String userId) {
		CommentEntity commentEntity = new CommentEntity();
		commentEntity.setTaskId(taskId);
		commentEntity.setTime(new Date());
		commentEntity.setType(CommentEntity.COMMENT_TRANSFERTASK);
		User user = userService.get(assign);
		if (user != null) {
			commentEntity.setUserName(user.getName());
		}

		commentEntity.setUserid(assign);

		// 查询历史任务
		HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
		commentEntity.setTaskName(task.getName());
		commentEntity.setProcessInstanceId(task.getProcessInstanceId());
		User user1 = userService.get(userId);
		String comment = "";
		if (user1 != null) {
			comment = user.getName() + "转办任务【" + task.getName() + "】给" + user1.getName();
		}
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}

	/**
	 * 撤回任务
	 */
	@Override
	public Integer revoke(String historyTaskId, String processInstanceId, User user) throws Exception {
		HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(historyTaskId)
				.singleResult();
		String taskName = task.getName();
		Command<Integer> cmd = new RevokeTaskCmd(historyTaskId, processInstanceId, this.runtimeService,
				this.workflowService, this.historyService);
		Integer revokeFlag = this.processEngineConfiguration.buildProcessEngine().getManagementService()
				.executeCommand(cmd);
		if (revokeFlag == 0) {
			doRevokeComment(historyTaskId, user.getId(), taskName, processInstanceId);
		}
		return revokeFlag;
	}

	// 撤回信息
	protected void doRevokeComment(String taskId, String userId, String taskName, String processInstanceId) {
		CommentEntity commentEntity = new CommentEntity();
		commentEntity.setTaskId(taskId);
		commentEntity.setTime(new Date());
		commentEntity.setType(CommentEntity.COMMENT_REVOKE);
		User user = userService.get(userId);
		if (user != null) {
			commentEntity.setUserName(user.getName());
		}
		commentEntity.setUserid(userId);
		commentEntity.setProcessInstanceId(processInstanceId);
		commentEntity.setTaskName(taskName);
		String comment = user.getName() + "撤回任务【" + taskName + "】";
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}

	/**
	 * 跳转（包括回退和向前）至指定活动节点
	 */
	@Override
	public void moveTo(String currentTaskId, String targetTaskDefinitionKey) throws Exception {
		TaskEntity taskEntity = (TaskEntity) this.taskService.createTaskQuery().taskId(currentTaskId).singleResult();
		moveTo(taskEntity, targetTaskDefinitionKey);
	}

	/**
	 * 跳转（包括回退和向前）至指定活动节点
	 */
	@Override
	public void moveTo(TaskEntity currentTaskEntity, String targetTaskDefinitionKey) throws Exception {
		ProcessDefinitionEntity pde = (ProcessDefinitionEntity) ((RepositoryServiceImpl) this.repositoryService)
				.getDeployedProcessDefinition(currentTaskEntity.getProcessDefinitionId());
		ActivityImpl activity = (ActivityImpl) pde.findActivity(targetTaskDefinitionKey);
		moveTo(currentTaskEntity, activity);

	}

	private void moveTo(TaskEntity currentTaskEntity, ActivityImpl activity) {
		Command<Void> deleteCmd = new DeleteActiveTaskCmd(currentTaskEntity, "jump", true);
		Command<Void> StartCmd = new StartActivityCmd(currentTaskEntity.getExecutionId(), activity);
		this.processEngineConfiguration.buildProcessEngine().getManagementService().executeCommand(deleteCmd);
		this.processEngineConfiguration.buildProcessEngine().getManagementService().executeCommand(StartCmd);
	}

	/**
	 * 读取已结束中的流程(admin查看)
	 *
	 * @return
	 */
	@Override
	public List<BaseVO> findFinishedProcessInstances(Page<BaseVO> page) {
		Map<String,Object>condition=page.getCondition();
		HistoricProcessInstanceQuery historQuery=null;
		if(StringUtils.isNotNull(condition.get("param"))) {
			Boolean b=true;
			try {
			Long.valueOf(condition.get("param").toString().trim());
			}catch(NumberFormatException e) {
				e.printStackTrace();
				b=false;
			}
			if(b) {
				historQuery = historyService.createHistoricProcessInstanceQuery().finished().processInstanceId(condition.get("param").toString().trim());
			}else {
				historQuery = historyService.createHistoricProcessInstanceQuery().finished().processInstanceNameLike("%"+condition.get("param").toString().trim()+"%");
			}
		}else {
			historQuery = historyService.createHistoricProcessInstanceQuery().finished();
		}
		Integer totalSum = historQuery.list().size();
		int[] pageParams = page.getPageParams(totalSum);
		List<HistoricProcessInstance> list = historQuery.orderByProcessInstanceEndTime().desc().listPage(pageParams[0],
				pageParams[1]);
		List<BaseVO> processList = new ArrayList<BaseVO>();

		for (HistoricProcessInstance historicProcessInstance : list) {
			String processInstanceId = historicProcessInstance.getId();
			List<HistoricVariableInstance> listVar = this.historyService.createHistoricVariableInstanceQuery()
					.processInstanceId(processInstanceId).list();
			for (HistoricVariableInstance var : listVar) {
				if ("serializable".equals(var.getVariableTypeName()) && "entity".equals(var.getVariableName())) {
					BaseVO base = (BaseVO) var.getValue();
					base.setHistoricProcessInstance(historicProcessInstance);
					base.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));
					processList.add(base);
					break;
				}
			}
		}

		return processList;
	}

	/**
	 * 各个审批人员查看自己完成的任务
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<BaseVO> findFinishedTaskInstances(User user, Page<BaseVO> page) throws Exception {
		Map<String,Object>condition=page.getCondition();
		HistoricTaskInstanceQuery historQuery=null;
		List<BaseVO> taskList = new ArrayList<BaseVO>();
		if(StringUtils.isNotNull(condition.get("param"))) {
			Boolean b=StringUtils.isNumeric(condition.get("param").toString().trim());
			if(b) {
				historQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(user.getId().toString())
						.finished().processInstanceId(condition.get("param").toString().trim());
			}else {
				//使用title在processInstanceEntity查询
				List<String>processInstanceIds=processInstanceIds=getProcessInstanceEntityLikeTitle(condition.get("param").toString().trim());
				if(processInstanceIds.size()>0) {
				  historQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(user.getId().toString())
						.finished().processInstanceIdIn(processInstanceIds);
				}
			}
		}else {
			historQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(user.getId().toString()).finished();
		}
		//HistoricTaskInstanceQuery historQuery = historyService.createHistoricTaskInstanceQuery()
		//		.taskAssignee(user.getId().toString()).finished();
		if(historQuery!=null) {
			Integer totalSum =Integer.parseInt(""+historQuery.count());
			int[] pageParams = page.getPageParams(totalSum);
			List<HistoricTaskInstance> list = historQuery.orderByHistoricTaskInstanceEndTime().desc()
					.listPage(pageParams[0], pageParams[1]);
			for (HistoricTaskInstance historicTaskInstance : list) {
				String processInstanceId = historicTaskInstance.getProcessInstanceId();
				List<HistoricVariableInstance> listVar = this.historyService.createHistoricVariableInstanceQuery()
						.processInstanceId(processInstanceId).list();
				for (HistoricVariableInstance var : listVar) {
					if ("serializable".equals(var.getVariableTypeName()) && "entity".equals(var.getVariableName())) {
						BaseVO base = (BaseVO) var.getValue();
						base.setHistoricTaskInstance(historicTaskInstance);
						base.setProcessInstanceId_(historicTaskInstance.getProcessInstanceId());
						ProcessDefinition processDefinition = getProcessDefinition(
								historicTaskInstance.getProcessDefinitionId());
						base.setVersion_(processDefinition.getVersion());
						base.setStartTime_(historicTaskInstance.getStartTime());
						base.setEndTime_(historicTaskInstance.getEndTime());
						String name = historicTaskInstance.getName();
						base.setTaskName(name);
						String taskId = historicTaskInstance.getId();
						base.setTaskId(taskId);
						base.setDeleteReason_(historicTaskInstance.getDeleteReason());
						base.setProcessDefinition(processDefinition);
						System.out.println(historicTaskInstance.getProcessInstanceId());
						taskList.add(base);
					}
				}
			}
		}
		return taskList;
	}
	/**
	 * 各个审批人员查看自己完成的任务
	 * 电脑上查看
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<BaseVO> findFinishedTaskInstancesPC(User user, Page<BaseVO> page) throws Exception {
		Map<String,Object>condition=page.getCondition();
		HistoricTaskInstanceQuery historQuery=null;
		List<BaseVO> taskList = new ArrayList<BaseVO>();
		if(StringUtils.isNotNull(condition.get("hasParams"))) {
			String hql="from ProcessInstanceEntity where 1=1";
			List<Object>params=new ArrayList<Object>();
			if(StringUtils.isNotNull(condition.get("processInstanceId"))) {
				hql+=" and processInstanceId=?";
				params.add(condition.get("processInstanceId"));
			}
			if(StringUtils.isNotNull(condition.get("title"))) {
				hql+=" and title like ?";
				params.add("%"+condition.get("title")+"%");
			}
			if(StringUtils.isNotNull(condition.get("userid"))) {
				hql+=" and userid=?";
				params.add(condition.get("userid"));
			}
			if(StringUtils.isNotNull(condition.get("businessKey"))) {
				hql+=" and businessKey=?";
				params.add(condition.get("businessKey"));
			}
			if(StringUtils.isNotNull(condition.get("startTimeStart"))) {
				hql+=" and startTime>=?";
				params.add(condition.get("startTimeStart"));
			}
			if(StringUtils.isNotNull(condition.get("startTimeEnd"))) {
				hql+=" and startTime<=?";
				params.add(condition.get("startTimeEnd"));
			}
			List<ProcessInstanceEntity> pies = processInstanceEntityDao.findByList(hql, params);
			List<String>processInstanceIds=new ArrayList<String>();
			if(pies.size()>0) {
				for(ProcessInstanceEntity pi:pies) {
					processInstanceIds.add(pi.getProcessInstanceId());
				}
				historQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(user.getId().toString())
						.finished().processInstanceIdIn(processInstanceIds);
			}
		}else {
			historQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(user.getId().toString()).finished();
		}
		//HistoricTaskInstanceQuery historQuery = historyService.createHistoricTaskInstanceQuery()
		//		.taskAssignee(user.getId().toString()).finished();
		if(historQuery!=null) {
			Integer totalSum = historQuery.list().size();
			int[] pageParams = page.getPageParams(totalSum);
			List<HistoricTaskInstance> list = historQuery.orderByHistoricTaskInstanceEndTime().desc()
					.listPage(pageParams[0], pageParams[1]);
			for (HistoricTaskInstance historicTaskInstance : list) {
				String processInstanceId = historicTaskInstance.getProcessInstanceId();
				List<HistoricVariableInstance> listVar = this.historyService.createHistoricVariableInstanceQuery()
						.processInstanceId(processInstanceId).list();
				for (HistoricVariableInstance var : listVar) {
					if ("serializable".equals(var.getVariableTypeName()) && "entity".equals(var.getVariableName())) {
						BaseVO base = (BaseVO) var.getValue();
						base.setHistoricTaskInstance(historicTaskInstance);
						base.setProcessInstanceId_(historicTaskInstance.getProcessInstanceId());
						ProcessDefinition processDefinition = getProcessDefinition(
								historicTaskInstance.getProcessDefinitionId());
						base.setVersion_(processDefinition.getVersion());
						base.setStartTime_(historicTaskInstance.getStartTime());
						base.setEndTime_(historicTaskInstance.getEndTime());
						String name = historicTaskInstance.getName();
						base.setTaskName(name);
						String taskId = historicTaskInstance.getId();
						base.setTaskId(taskId);
						base.setDeleteReason_(historicTaskInstance.getDeleteReason());
						base.setProcessDefinition(processDefinition);
						System.out.println(historicTaskInstance.getProcessInstanceId());
						taskList.add(base);
					}
				}
			}
		}
		return taskList;
	}

	private List<String> getProcessInstanceEntityLikeTitle(String title) {
		List<String>processInstanceIds=new ArrayList<String>();
		String hql="from ProcessInstanceEntity where title like ?";
		List<ProcessInstanceEntity> vos = processInstanceEntityDao.find(hql, "%"+title+"%");
		if(vos.size()>0) {
			for(ProcessInstanceEntity vo:vos) {
				processInstanceIds.add(vo.getProcessInstanceId());
			}
		}
		return processInstanceIds;
	}

	/**
	 * 查看正在运行的流程
	 */
	@Override
	public List<ProcessInstance> listRuningProcess(Page<ProcessInstance> page) throws Exception {
		ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
		int[] pageParams = page.getPageParams(processInstanceQuery.list().size());
		List<ProcessInstance> list = processInstanceQuery.orderByProcessInstanceId().desc().listPage(pageParams[0],
				pageParams[1]);
		return list;
	}

	/**
	 * 激活流程
	 */
	@Override
	public void activateProcessInstance(String processInstanceId) throws Exception {
		runtimeService.activateProcessInstanceById(processInstanceId);

	}

	/**
	 * 挂起流程
	 */
	@Override
	public void suspendProcessInstance(String processInstanceId) throws Exception {
		runtimeService.suspendProcessInstanceById(processInstanceId);
	}

	@Override
	public void addProcessByDynamic() throws Exception {

		final String PROCESSID = "process_test_1";
		BpmnModel model = new BpmnModel();
		Process process = new Process();

		process.setId(PROCESSID);
		process.setName("动态流程测试");

		process.addFlowElement(createStartEvent());
		process.addFlowElement(createUserTask("userTask1", "用户任务1"));
		process.addFlowElement(createExclusiveGateway("gateway1"));
		process.addFlowElement(createUserTask("userTask2", "用户任务2"));
		process.addFlowElement(createExclusiveGateway("gateway2"));
		process.addFlowElement(createUserTask("userTask3", "用户任务3"));
		process.addFlowElement(createEndEvent());

		process.addFlowElement(createSequenceFlow("startEvent", "userTask1", "flow1", "", ""));
		process.addFlowElement(createSequenceFlow("userTask1", "gateway1", "flow2", "", ""));
		process.addFlowElement(createSequenceFlow("gateway1", "userTask2", "flow3", "同意", "${isPass}"));
		process.addFlowElement(createSequenceFlow("gateway1", "userTask3", "flow4", "不同意", "${!isPass}"));
		process.addFlowElement(createSequenceFlow("userTask2", "endEvent", "flow5", "", ""));
		process.addFlowElement(createSequenceFlow("userTask3", "gateway2", "flow6", "", ""));
		process.addFlowElement(createSequenceFlow("gateway2", "userTask1", "flow7", "同意", "${reApply}"));
		process.addFlowElement(createSequenceFlow("gateway2", "endEvent", "flow8", "结束", "${!reApply}"));

		model.addProcess(process);

		// 生成流程图片信息
		BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(model);
		bpmnAutoLayout.execute();

		// 部署流程
		Deployment deployment = this.repositoryService.createDeployment().addBpmnModel(PROCESSID + ".bpmn", model)
				.name("动态流程测试").deploy();

		/*
		 * // 启动流程 ProcessInstance processInstance =
		 * this.runtimeService.startProcessInstanceByKey(PROCESSID);
		 * 
		 * // 导出流程图片 InputStream processDiagram =
		 * this.repositoryService.getProcessDiagram(processInstance.
		 * getProcessDefinitionId()); FileUtils.copyInputStreamToFile(processDiagram,
		 * new File("D:/deployments/"+PROCESSID+".png"));
		 * 
		 * // 导出流程文件(BPMN xml) InputStream processBpmn =
		 * this.repositoryService.getResourceAsStream(deployment.getId(),
		 * PROCESSID+".bpmn"); FileUtils.copyInputStreamToFile(processBpmn,new
		 * File("D:/deployments/"+PROCESSID+".bpmn"));
		 */

	}

	@Override
	public Map<String, Object> queryHistoricActivityInstances(String processInstanceId) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
				.processInstanceId(processInstanceId).list();
		for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
			if (historicActivityInstance.getTaskId() != null) {
				resultMap.put("processInsInsId", historicActivityInstance.getProcessInstanceId());
				resultMap.put("activityName", historicActivityInstance.getActivityName());
				resultMap.put("startTime", historicActivityInstance.getStartTime());
				resultMap.put("endTime", historicActivityInstance.getEndTime());
				resultMap.put("taskId", historicActivityInstance.getTaskId());
				String executeUserName = "";
				User executeUser = userService.get(historicActivityInstance.getAssignee());
				if (executeUser != null) {
					executeUserName = executeUser.getName();
				}
				// 任务执行人
				resultMap.put("executeUserName", executeUserName);
			}
		}
		return resultMap;
	}

	// 查询任务待审批人及任务
	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> findTodoTaskAssigneeOrCandidateUsers(String processInstanceId) {
		String userNames = "";
		Map<String, Object> map = new HashMap<String, Object>();
		Set<String> userIds = new HashSet<String>();
		map = findTodoTaskAssigneeOrCandidateUserIds(processInstanceId);
		userIds = (Set<String>) map.get("userIds");
		if (StringUtils.isNotNull(userIds)) {
			for (String userId : userIds) {
				User user = userService.get(userId);
				if (user != null) {
					userNames += user.getName() + ",";
				}
			}
			log.info("userNames={}", userNames);
			if (!userNames.equals("")) {
				userNames = userNames.substring(0, userNames.lastIndexOf(","));
			}
		}
		map.put("userNames", userNames);
		return map;
	}

	// 查询待办人
	@Override
	public Map<String, Object> findTodoTaskAssigneeOrCandidateUserIds(String processInstanceId) {
		Map<String, Object> map = new HashMap<String, Object>();
		Set<String> userIds = new HashSet<String>();
		Set<String> taskNames = new HashSet<String>();
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
		if (tasks.size() > 0) {
			for (Task task : tasks) {
				taskNames.add(task.getName());
				String assignee = task.getAssignee();
				if (assignee != null) {
					userIds.add(assignee);
				} else {
					List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
					if (identityLinks.size() > 0) {
						for (IdentityLink identityLink : identityLinks) {
							String type = identityLink.getType();
							if ("participant".equals(type)) {
								// 任务参与人
								userIds.add(identityLink.getUserId());
							}
							if ("candidate".equals(type)) {
								// 候选组
								if(StringUtils.isNotNull(identityLink.getGroupId())) {
									List<org.activiti.engine.identity.User> users = identityService.createUserQuery()
											.memberOfGroup(identityLink.getGroupId()).list();
									if (users.size() > 0) {
										for (org.activiti.engine.identity.User user : users) {
											userIds.add(user.getId());
										}
									}
								}
								//候选人
								if(StringUtils.isNotNull(identityLink.getUserId())){
									userIds.add(identityLink.getUserId());
								}
							}
						}
					}
				}

			}
		}
		map.put("userIds", userIds);
		map.put("taskName", taskNames.toString().replace("[", "").replace("]", ""));
		return map;
	}

	/**
	 * 加签
	 */
	@Override
	public void addSign(String taskId, String assignee) {
		processEngine.getManagementService().executeCommand(new ShareniuCountersignAddCmd(taskId, assignee));
	}

	/**
	 * 减签
	 */
	@Override
	public void minSign(String taskId) {
		processEngine.getManagementService().executeCommand(new ShareniuCountersignMinCmd(taskId));
	}

	/**
	 * 作废流程,作废后不能恢复
	 */
	@Override
	public void doInvalidProcess(String processInstanceId, String tableName) {
		ProcessInstanceEntity processInstanceEntity = processInstanceEntityDao.get(ProcessInstanceEntity.class,
				processInstanceId);
		if(processInstanceEntity!=null) {
			if ((processInstanceEntity.getStatus() == processInstanceEntity.FAIL_STATUS)
					|| processInstanceEntity.getStatus() == processInstanceEntity.COMPLETE_STATUS) {
				throw new MyException("流程【" + processInstanceId + "】已审批结束，不能作废");
			}
			doInvalidComment(processInstanceEntity.getUserid(), processInstanceId);
		}
		runtimeService.suspendProcessInstanceById(processInstanceId);// 挂起流程
		runtimeService.deleteProcessInstance(processInstanceId, "作废流程");// 删除流程
		//更新实体
		if(tableName!=null) {
			String sql="update "+tableName+" set status=:status where processInstanceId=:processInstanceId";
			Map<String,Object>paramMap=new HashMap<String,Object>();
			paramMap.put("status", BaseVO.INVALID);
			paramMap.put("processInstanceId", processInstanceId);
			jdbcDao.saveOrUpdate(sql, paramMap);
		}
		String hql = "update ProcessInstanceEntity set status=? where processInstanceId=?";
		processInstanceEntityDao.execute(hql, ProcessInstanceEntity.INVALID_STATUS, processInstanceId);
	}

	// 作废流程信息
	protected void doInvalidComment(String userId, String processInstanceId) {
		CommentEntity commentEntity = new CommentEntity();
		commentEntity.setTime(new Date());
		commentEntity.setType(CommentEntity.COMMENT_INVALID);
		User user = userService.get(userId);
		if (user != null) {
			commentEntity.setUserName(user.getName());
		}
		commentEntity.setUserid(userId);
		commentEntity.setProcessInstanceId(processInstanceId);
		String comment = user.getName() + "作废流程【" + processInstanceId + "】";
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}
	
	/**
	 * 并行分支节点跳转
	 * @param currentTaskId
	 * @param targetTaskDefinitionKey
	 */
	@Override
	public void paralleMoveTo(String currentTaskId,String targetTaskDefinitionKey){
		TaskEntity taskEntity = (TaskEntity) this.taskService.createTaskQuery().taskId(currentTaskId).singleResult();
		ReadOnlyProcessDefinition processDefinitionEntity = (ReadOnlyProcessDefinition) repositoryService
				.getProcessDefinition(taskEntity.getProcessDefinitionId());
		// 目标节点
		ActivityImpl destinationActivity = (ActivityImpl) processDefinitionEntity.findActivity(targetTaskDefinitionKey);
		String executionId =taskEntity.getExecutionId();
		String parentId = taskEntity.getProcessInstanceId();
		// 当前节点
		ActivityImpl currentActivity = (ActivityImpl) processDefinitionEntity.findActivity(taskEntity.getTaskDefinitionKey());
		ActivityBehavior activityBehavior = currentActivity.getActivityBehavior();
		System.out.println(activityBehavior.getClass().getName());
		processEngine.getManagementService().executeCommand(
				new ParallelJumpCmd(executionId, parentId, destinationActivity, null, currentActivity));
	}

	
	/**
	 * 多实例跳转
	 * @param currentTaskId
	 * @param targetTaskDefinitionKey
	 */
	@Override
	public void multiInstanceMoveTo(String currentTaskId,String targetTaskDefinitionKey){
		TaskEntity taskEntity = (TaskEntity) this.taskService.createTaskQuery().taskId(currentTaskId).singleResult();
		ReadOnlyProcessDefinition processDefinitionEntity = (ReadOnlyProcessDefinition) repositoryService
				.getProcessDefinition(taskEntity.getProcessDefinitionId());
		// 目标节点
		ActivityImpl destinationActivity = (ActivityImpl) processDefinitionEntity.findActivity(targetTaskDefinitionKey);
		String executionId =taskEntity.getExecutionId();
		String parentId = taskEntity.getProcessInstanceId();
		// 当前节点
		ActivityImpl currentActivity = (ActivityImpl) processDefinitionEntity.findActivity(taskEntity.getTaskDefinitionKey());
		ActivityBehavior activityBehavior = currentActivity.getActivityBehavior();
		System.out.println(activityBehavior.getClass().getName());
		processEngine.getManagementService().executeCommand(
				new MultiInstanceJumpCmd(executionId, parentId, destinationActivity, null, currentActivity));
	}
	
	/**
	 * 通过流程Id查询待办任务
	 */
	@Override
	public List<Task> findByProcessInstanceId(String processInstanceId) {
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
		return tasks;
	}

	
	
}
